package itheima.jiemian;

import com.sun.source.tree.NewArrayTree;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class GameFrame extends JFrame implements KeyListener, ActionListener {
    //JFrame表示界面
    //子类也表示界面
    //规定GameFrame表示游戏的主界面
    //以后跟游戏相关的所有逻辑都写在这个类中
    //4.创建一个二维数组
    int[][] date = new int[4][4];
    //记录空白方块在二维数组中的位置
    int x = 0;
    int y = 0;
    //定义路径
    String path = "..\\day25\\image\\girl\\girl4\\";

    //判断是否正确,定义一个二维数组,存储正确的数据
    int[][] wim = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 0}};
    //定义变量用来统计步数
    int step = 0;

    //创建选项下面的条目对象


    JMenuItem replyItem = new JMenuItem("重新游戏");
    JMenuItem reLoginItem = new JMenuItem("重新登录");
    JMenuItem closeItem = new JMenuItem("关闭游戏");

    JMenuItem accountItem = new JMenuItem("我的微信号");
    JMenuItem moneyItem = new JMenuItem("谢谢打赏");
    JMenuItem QQyItem = new JMenuItem("我的QQ号");
    //创建JMenuItem的对象
    JMenuItem girl = new JMenuItem("美女");
    JMenuItem animal = new JMenuItem("动物");
    JMenuItem sport = new JMenuItem("运动");


    //目的: 用来管理数据
    //加载图片的时候,会根据二维数组的数据进行加载
    public GameFrame() {//在主界面APP里面,程序启动会调用空参构造GameFrame方法,起到初始化作用
        //初始化界面
        initJFrame();
        //初始化菜单
        initJmenuBar();

        //初始化数据(打乱)
        initDate();

        //初始化图片(根据打乱之后的结果去加载图片)
        initImage();
        //让他显示出来，建议最后
        this.setVisible(true);

    }


    //初始化数据(打乱)
    private void initDate() {
        //需求
        //把一个二维数组中的数据:0~15打乱顺序
        //然后再按照4个一组的方式添加到二维数组当中

        //1.定义一个一维数组
        int[] tempArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
        //2.打乱数组中的顺序
        //遍历数组,得到每一个元素,拿到每一个元素跟随机索引上的数据进行数据交换
        Random r = new Random();
        for (int i = 0; i < tempArray.length; i++) {
            int index = r.nextInt(tempArray.length);
            int temp = tempArray[i];
            tempArray[i] = tempArray[index];
            tempArray[index] = temp;
        }
        //3.打印先看看

        //5.解法一:
        //遍历一维数组tempArr得到每一个元素,把每个元素一次添加在二维数组当中
        for (int i = 0; i < tempArray.length; i++) {
            if (tempArray[i] == 0) {
                x = i / 4;
                y = i % 4;
            }
            date[i / 4][i % 4] = tempArray[i];


        }


        //解法二:
        //遍历二维数组给里面的每一个数据赋值
//        int index = 0;
//        for (int i = 0; i < date.length; i++) {
//            for (int j = 0; j < date[i].length; j++) {
//                date[i][j] = tempArray[index++];
//            }
//
//        }
    }


    //初始化图片
    /*
    首先 创建ImageIcon的对象,
    并指定图片在电脑中的位置,然后创建一个JLabel的对象,
    把图片交给JLabel,在把这个整体放在界面当中
     */
    private void initImage() {

        //清空原本已经有的图片
        this.getContentPane().removeAll();


        if (victory()) {
            //显示胜利图片
            JLabel winjLabel = new JLabel(new ImageIcon("D:\\Java学习\\java-learning\\day25\\image\\win.png"));
            //设置位置
            winjLabel.setBounds(203, 283, 197, 73);
            //显示图片 把管理容器添加在界面当中
            this.getContentPane().add(winjLabel);
        }

        JLabel stepCount = new JLabel("步数" + step);
        stepCount.setBounds(50, 30, 100, 20);
        this.getContentPane().add(stepCount);

        //初始化图片
        //直接用循环解决
        //方法2
        //添加图片的时候,就需要按照二维数组中管理的数据添加图片了
        // 定义图片的基础路径
        //外循环是把内循环执行4次
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                //内循环----表示在一行添加了4张图片
                //获取当前要加载的图片的序号
                int num = date[i][j];
                // 创建一个ImageIcon对象
                ImageIcon icon = new ImageIcon(path + num + ".jpg");
                // 创建一个JLabel对象(管理容器)
                JLabel label = new JLabel(icon);

                // 指定图片的位置
                label.setBounds(j * 105 + 83, i * 105 + 134, 105, 105);
                //+83     +134是为了加图片框
                //给图片添加边框
                //1表示图片凹下去
                //0表示图片凸下去
                label.setBorder(new BevelBorder(1));

                // 把管理容器添加在界面当中
                this.getContentPane().add(label);
            }

        }
        //添加背景图片
        //创建一个ImageIcon的对象
        ImageIcon bg = new ImageIcon("..\\day25\\image\\background.png");
        //创建一个JLabel的对象(管理容器)
        JLabel label = new JLabel(bg);
        label.setBounds(40, 40, 508, 560);
        //把背景界面添加在界面当中
        this.getContentPane().add(label);
        //刷新一下界面
        this.getContentPane().repaint();


//

//


//        //创建一个ImageIcon的对象
//        ImageIcon i = new ImageIcon("D:\\Java学习\\java-learning\\day25\\image\\girl\\girl1\\2.jpg");
//        //创建一个JLabel的对象(管理容器)
//        JLabel j1 = new JLabel(i);
//        //指定图片的位置
//        j1.setBounds(0, 0, 105, 105);//一张图片宽105个像素,长同理
//        //把管理容器添加在界面当中
//        this.getContentPane().add(j1);//先获取隐藏的容器在添加add方法,把管理容器添加在界面当中
//
//        //创建一个JLabel的对象(管理容器)
//        JLabel j2 = new JLabel(new ImageIcon("D:\\Java学习\\java-learning\\day25\\image\\girl\\girl1\\3.jpg"));
//        //指定图片的位置
//        j2.setBounds(105, 0, 105, 105);//一张图片宽105个像素,长同理
//        //把管理容器添加在界面当中
//        this.getContentPane().add(j2);//先获取隐藏的容器在添加add方法,把管理容器添加在界面当中


        //方法一:
//        // 定义图片的基础路径
//        String basePath = "D:\\Java学习\\java-learning\\day25\\image\\girl\\girl1\\";
//        // 创建一个存储图片文件名的列表
//        List<String> imagePaths = new ArrayList<>();
//        for (int i = 1; i <= 16; i++) {
//            imagePaths.add(basePath + i + ".jpg");//因为图片是从1开始的比如1.jpg
//        }
//        // 打乱图片顺序
//        Collections.shuffle(imagePaths);
//        // 循环添加16张打乱顺序的图片
//        for (int j = 0; j < 16; j++) {
//            // 创建一个ImageIcon对象
//            ImageIcon icon = new ImageIcon(imagePaths.get(j));
//
//
//            // 创建一个JLabel对象(管理容器)
//            JLabel label = new JLabel(icon);
//
//            // 计算图片的位置（假设每行4张图片）
//            int row = j / 4; // 行号  行号从第0行开始的 然后按列进行拷贝
//            int col = j % 4; // 列号
//
//            // 指定图片的位置
//            label.setBounds(col * 105, row * 105, 105, 105);
//
//            // 把管理容器添加在界面当中
//            this.getContentPane().add(label);
//        }


    }


    private void initJmenuBar() {
        //创建整个的菜单对象
        JMenuBar jmenuBar = new JMenuBar();
        //创建更换图片
        JMenu changeImage = new JMenu("更换图片");
        //创建菜单上面2个选项对象(功能,关于我们)
        JMenu funJmenu = new JMenu("功能");
        JMenu aboutJmenu = new JMenu("关于我们");


        //4.把美女，动物，运动添加到更换图片当中
        changeImage.add(girl);
        changeImage.add(animal);
        changeImage.add(sport);


        //5.把更换图片，重新游戏，重新登录，关闭游戏等添加到功能当中
        //将每一个选项下面的条目添加在这个选项中
        funJmenu.add(replyItem);
        funJmenu.add(reLoginItem);
        funJmenu.add(closeItem);
        funJmenu.add(changeImage);

        aboutJmenu.add(accountItem);
        aboutJmenu.add(moneyItem);
        aboutJmenu.add(QQyItem);


        //将菜单下的2个选项添加在菜单中
        jmenuBar.add(funJmenu);
        jmenuBar.add(aboutJmenu);

        //给整个界面设置菜单
        this.setJMenuBar(jmenuBar);


        //给条目绑定事件  /给整个界面添加动作监听事件
        replyItem.addActionListener(this);//重新游戏
        reLoginItem.addActionListener(this);//重新登录
        closeItem.addActionListener(this);//关闭游戏
        accountItem.addActionListener(this);//我的微信号
        moneyItem.addActionListener(this);//我的打款码
        QQyItem.addActionListener(this);//我的QQ号
        girl.addActionListener(this);
        animal.addActionListener(this);
        sport.addActionListener(this);
    }

    private void initJFrame() {
        //设置界面的宽高
        this.setSize(603, 680);
        //设置界面的标题
        this.setTitle("拼图单机版 v1.0");
        //设置界面置顶
        this.setAlwaysOnTop(true);
        //设置界面居中
        this.setLocationRelativeTo(null);
        //设置游戏的关闭模式
        this.setDefaultCloseOperation(3);//3就是关掉其中一个窗口就关闭了虚拟机
        //取消默认的居中放置,只有取消了才会按照XY轴的形式添加组件
        this.setLayout(null);
        //给整个界面添加键盘监听事件
        this.addKeyListener(this);


//        //创建一个按钮对象
//        JButton jtb = new JButton("开始游戏");
//        //设置位置和宽高
//        jtb.setBounds(0, 0, 100, 50);
//        //给按钮添加动作监听
//        //jtb表示组件对象,表示你要给哪个组件添加事件
//        //addActionListener:表示我要给组件添加哪个事件监听(动作监听鼠标左键点击,空格)
//        //jtb.addActionListener(new MyaddActionListener());//addActionListener是一个接口 ,需要调用这个接口的实现类对象
//        //当鼠标左键单价这个jtb按钮后,就会执行MyaddActionListener()这里面的代码 ------  达咩
//
//        //当一个类只用一次的时候我们可以用匿名内部类
//        jtb.addActionListener(new ActionListener() {
//            @Override
//            public void actionPerformed(ActionEvent e) {
//                System.out.println("达咩~不要点我啊");
//            }
//        });
//
//
//        this.getContentPane().add(jtb);
//        //要把按钮添加在整个界面当中

    }


    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override //键盘按下不松的时候调用这个方法
    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();
        if (code == 65) {//这个65就是按下A
            //把界面所有的图片删除
            this.getContentPane().removeAll();
            //加载第一张完整的图片,
            JLabel all = new JLabel(new ImageIcon(path + "all.jpg"));
            all.setBounds(83, 134, 420, 420);
            //界面显示加载图片
            this.getContentPane().add(all);
            //加载第二张背景图片
            //添加背景图片
            //创建一个ImageIcon的对象
            ImageIcon bg = new ImageIcon("..\\day25\\image\\background.png");
            //创建一个JLabel的对象(管理容器)
            JLabel label = new JLabel(bg);
            label.setBounds(40, 40, 508, 560);
            //把背景界面添加在界面当中
            this.getContentPane().add(label);
            //刷新一下界面
            this.getContentPane().repaint();
        }


    }

    @Override
    public void keyReleased(KeyEvent e) {

        if (victory()) {//胜利就结束方法,不能在移动了
            return;
        }
        //对上,下,左,右进行判断
        //左上右下 分别是37,38,30,40
        int code = e.getKeyCode();
        System.out.println(code);

        if (code == 37) {
            System.out.println("向左移动");
            //边界问题
            if (y == 3) {
                return;
            }
            //逻辑
            ////把空白块右方的数字向左移动
            //x,y表示空白方快
            //x,y-1表示空白左方的数字
            //把空白方块左方x的数字赋值给空白方快
            date[x][y] = date[x][y + 1];
            date[x][y + 1] = 0;//就是留出空白方快的位置
            y++;
            //每移动一次计数器就自增一次
            step++;
            //调用方法按照最新的数字加载图片
            initImage();

        } else if (code == 38) {
            System.out.println("向上移动");
            //边界问题
            if (x == 3) {
                return;
            }
            //逻辑
            //把空白块下方的数字向上移动
            //x,y表示空白方快
            //x+1,y表示空白下方的数字
            //把空白方块下方的数字赋值给空白方快
            date[x][y] = date[x + 1][y];
            date[x + 1][y] = 0;//就是留出空白方快的位置
            x++;
            //每移动一次计数器就自增一次
            step++;
            //调用方法按照最新的数字加载图片
            initImage();


        } else if (code == 39) {
            System.out.println("向右移动");
            //边界问题
            if (y == 0) {
                return;
            }
            //逻辑
            //把空白块左方的数字向右移动
            //x,y表示空白方快
            //x,y-1表示空白右方的数字
            //把空白方块右方的数字赋值给空白方快
            date[x][y] = date[x][y - 1];
            date[x][y - 1] = 0;//就是留出空白方快的位置
            y--;
            //每移动一次计数器就自增一次
            step++;
            //调用方法按照最新的数字加载图片
            initImage();
        } else if (code == 40) {
            System.out.println("向下移动");
            //边界问题
            if (x == 0) {
                return;
            }
            //逻辑
            //把空白块上方的数字向下移动
            //x,y表示空白方快
            //x+1,y表示空白下方的数字
            //把空白方块下方的数字赋值给空白方快
            date[x][y] = date[x - 1][y];
            date[x - 1][y] = 0;//就是留出空白方快的位置
            x--;
            //每移动一次计数器就自增一次
            step++;
            //调用方法按照最新的数字加载图片
            initImage();
        } else if (code == 65) {
            initImage();
        } else if (code == 87) { //w键
            date = new int[][]{
                    {1, 2, 3, 4},
                    {5, 6, 7, 8},
                    {9, 10, 11, 12},
                    {13, 14, 15, 0},
            };
            initImage();
        }

    }

    //判断date数组中的数据是否和win数组中是否相同
    //如果相同返回true,不同false
    public boolean victory() {
        for (int i = 0; i < date.length; i++) {
            for (int j = 0; j < date[i].length; j++) {
                if (date[i][j] != wim[i][j]) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //获取当前被点击的条目对象
        Object obj = e.getSource();
        if (obj == replyItem) {
            System.out.println("重新游戏");
            //计数器清0
            step = 0;
            //再次打乱二维数组中的数据
            initDate();
            //重新加载图片(打乱)
            initImage();
        } else if (obj == reLoginItem) {
            System.out.println("重新登陆");
            //关闭游戏界面
            this.setVisible(false);
            //打开登录界面
            new LoginFrame();//调用空参构造

        } else if (obj == closeItem) {
            //直接关闭虚拟机即可
            System.exit(0);
        } else if (obj == accountItem) {
            System.out.println("微信号");
            //创建一个弹框对象
            JDialog jd = new JDialog();
            //创建一个管理图片的容器对象JLabel
            JLabel jLabel = new JLabel(new ImageIcon("..\\day25\\Snipaste_2024-06-23_15-59-16.png"));
            //设置位置和宽高
            jLabel.setBounds(0, 0, 477, 581);
            //把图片添加到弹框里面
            jd.getContentPane().add(jLabel);
            //给弹框设置大小
            jd.setSize(700, 700);
            //让弹框置顶
            jd.setAlwaysOnTop(true);
            //让弹框居中
            jd.setLocationRelativeTo(null);
            //让弹框不关闭则无法操作下面的界面
            jd.setModal(true);
            //显示图片
            jd.setVisible(true);


        } else if (obj == moneyItem) {
            System.out.println("打款码");
            //创建一个弹框对象
            JDialog jd = new JDialog();
            //创建一个管理图片的容器对象JLabel
            JLabel jLabel = new JLabel(new ImageIcon("..\\day25\\Snipaste_2024-06-23_16-18-04.png"));
            //设置位置和宽高
            jLabel.setBounds(0, 0, 635, 687);
            //把图片添加到弹框里面
            jd.getContentPane().add(jLabel);
            //给弹框设置大小
            jd.setSize(700, 700);
            //让弹框置顶
            jd.setAlwaysOnTop(true);
            //让弹框居中
            jd.setLocationRelativeTo(null);
            //让弹框不关闭则无法操作下面的界面
            jd.setModal(true);
            //显示图片
            jd.setVisible(true);


        } else if (obj == QQyItem) {
            System.out.println("QQ号");
            //创建一个弹框对象
            JDialog jd = new JDialog();
            //创建一个管理图片的容器对象JLabel
            JLabel jLabel = new JLabel(new ImageIcon("..\\day25\\Snipaste_2024-06-23_16-14-15.png"));
            //设置位置和宽高
            jLabel.setBounds(0, 0, 418, 551);
            //把图片添加到弹框里面
            jd.getContentPane().add(jLabel);
            //给弹框设置大小
            jd.setSize(600, 600);
            //让弹框置顶
            jd.setAlwaysOnTop(true);
            //让弹框居中
            jd.setLocationRelativeTo(null);
            //让弹框不关闭则无法操作下面的界面
            jd.setModal(true);
            //显示图片
            jd.setVisible(true);
        }

    }
}
